import React from 'react'
import { Form, Button, Toask, Loading, Progress } from '@/component/index'
import cssStyle from './index.module.css'
import { upload, uploadChunk, merge } from '@/api/upload.js'
import SparkMD5 from 'spark-md5'

const chunkSize = 5 * 1024 * 1024
const hashFile = (file) => {
    return new Promise((resolve, reject) => { 
      const chunks = Math.ceil(file.size / chunkSize);
      let currentChunk = 0;
      const spark = new SparkMD5.ArrayBuffer();
      const fileReader = new FileReader();
      function loadNext() {
        const start = currentChunk * chunkSize;
        const end = Math.min(file.size, start + chunkSize)
        fileReader.readAsArrayBuffer(file.slice(start, end));
      }
      fileReader.onload = e => {
        spark.append(e.target.result); // Append array buffer
        currentChunk += 1;
        if (currentChunk < chunks) {
          loadNext();
        } else {
          const result = spark.end();
          // 如果单纯的使用result 作为hash值的时候, 如果文件内容相同，而名称不同的时候
          // 想保留两个文件无法保留。所以把文件名称加上。
          const sparkMd5 = new SparkMD5();
          sparkMd5.append(result);
          sparkMd5.append(file.name);
          const hexHash = sparkMd5.end();
          resolve(hexHash);
        }
      };
      fileReader.onerror = () => {
        console.warn('文件读取失败！');
      };
      loadNext();
    }).catch(err => {
        console.log(err);
    });
}

class FormComponent extends React.Component{
    constructor(props){
        super(props)
        this.state = {
            percent: 0,
            form: {
                text: 'newsoul',
                password: 'react-ui',
                textarea: '',
                radio: '3',
                checkbox: [],
                select: '',
                selectMultiple: [],
                switch1: true,
                switch2: false,
                file: '',
                img: '',
                time: '',
                calendar: '2021-10-19 12:00:00',
            },
            showPassword: false,
            checked: false
        }
        this.rules = {
            text(value){
                if(value === ''){
                    return '不能为空'
                }
                return true
            },
            password(value){
                if(value === ''){
                    return '不能为空'
                }else if(value.length < 6){
                    return '长度需大于6'
                }
                return true
            },
            textarea(value){
                if(value === ''){
                    return '不能为空'
                }
                return true
            },
            radio(value){
                if(value === ''){
                    return '请选择一项'
                }
                return true
            },
            checkbox(value){
                if(value.length === 0){
                    return '至少选择一项'
                }
                return true
            },
            select(value){
                if(value === ''){
                    return '请选择一项'
                }
                return true
            },
            selectMultiple(value){
                if(value.length === 0){
                    return '至少选择一项'
                }
                return true
            },
            time(value){
                if(value === ''){
                    return '请选择时间'
                }
                return true
            }
        }
        this.rulesRef = React.createRef()
    }
    setFormData = prop => {
        return value => {
            this.setState(state => {
                state.form[prop] = value
                return state
            })
        }
    }
    uploadChunk = async (file, chunkIndex, hash) => {
        try {
            let formData = new FormData()
            formData.append('file', file)
            formData.append('chunkIndex', chunkIndex)
            formData.append('hash', hash)
            const res = await uploadChunk(formData, e => {
                if (e.lengthComputable) {
                    const percent = (e.loaded / e.total) * 100
                    // this.setState({
                    //     percent
                    // })
                }
            })
            if (res.status) {
                return Promise.resolve()
            }
            return Promise.reject()
        } catch (error) {
            console.log(error)
        }
    }
    upload = async file => {
        try {
            this.setState({
                percent: 0
            })
            let formData = new FormData()
            formData.append('file', file)
            const res = await upload(formData, e => {
                if (e.lengthComputable) {
                    const percent = parseInt((e.loaded / e.total) * 100)
                    this.setState({
                        percent
                    })
                }
            })
            console.log(res)
            if (res.status) {
                return Promise.resolve()
            }
            return Promise.reject()
        } catch (error) {
            console.log(error)
            return Promise.reject()
        }
    }
    getFile = (type, isChunk) => {
        return async file => {
            file = file[0]
            let toask = Toask()
            let loading = Loading()
            loading.showLoading('上传中...')
            if (isChunk) {
                const hash = await hashFile(file)
                const chunkNum = Math.ceil(file.size / chunkSize)
                const chunkFile = []
                for (let i = 0; i < chunkNum; i += 1) {
                    const start = i * chunkSize
                    const end = (start + chunkSize) >= file.size ? file.size : start + chunkSize
                    chunkFile.push(file.slice(start, end))
                }
                const uploadList = []
                for (let i = 0; i < chunkFile.length; i += 1) {
                    uploadList.push(this.uploadChunk(chunkFile[i], i, hash))
                }
                const start = new Date().getTime()
                Promise.all(uploadList).then(async () => {
                    try {
                        const res = await merge({
                            name: file.name,
                            total: chunkNum,
                            hash
                        })
                        if (res.status) {
                            const end = new Date().getTime()
                            console.log((end - start) / 1000)
                            toask.showToask({
                                type: 'success',
                                title: '上传成功',
                                duration: 1500
                            })
                        } else {
                            toask.showToask({
                                type: 'error',
                                title: '上传失败',
                                duration: 1500
                            })
                        }
                    } catch (error) {
                        toask.showToask({
                            type: 'error',
                            title: '上传失败',
                            duration: 1500
                        })
                    } finally {
                        loading.hideLoading()
                    }
                }).catch(() => {
                    toask.showToask({
                        type: 'error',
                        title: '上传失败',
                        duration: 1500
                    })
                })
            } else {
                try {
                    const start = new Date().getTime()
                    await this.upload(file)
                    const end = new Date().getTime()
                    console.log((end - start) / 1000)
                    toask.showToask({
                        type: 'success',
                        title: '上传成功',
                        duration: 1500
                    })
                } catch (error) {
                    toask.showToask({
                        type: 'error',
                        title: '上传失败',
                        duration: 1500
                    })
                } finally {
                    loading.hideLoading()
                }
            }
        }
    }
    getMultipleFile = (type) => {
        return file => {
            let toask = Toask()
            let loading = Loading()
            loading.showLoading('上传中...')
            try {
                const uploadList = []
                for (let i = 0; i < file.length; i += 1) {
                    uploadList.push(this.upload(file[i]))
                }
                const start = new Date().getTime()
                Promise.all(uploadList).then(() => {
                    const end = new Date().getTime()
                    console.log((end - start) / 1000)
                    toask.showToask({
                        type: 'success',
                        title: '上传成功',
                        duration: 1500
                    })
                }).catch(() => {
                    toask.showToask({
                        type: 'error',
                        title: '上传失败',
                        duration: 1500
                    })
                }).finally(() => {
                    loading.hideLoading()
                })
            } catch (error) {
                loading.hideLoading()
                toask.showToask({
                    type: 'error',
                    title: '上传失败',
                    duration: 1500
                })
            }
        }
    }
    submit(){
        this.rulesRef.current.validate(valid => {
            if(valid){
                console.log(this.state.form)
            }
        })
    }
    showPassword = () => {
        this.setState(state => {
            state.showPassword = !state.showPassword
            return state
        })
    }
    _setFormData = (val, props) => {
        this.setState(state => {
            state.form[props.name] = val
            return state
        })
    }
    render(){
        return(
            <div className={ cssStyle.container }>
                <Form.form form={ this.state.form } ref={ this.rulesRef } rules={ this.rules }>
                    <Form.item label="input：" labelWidth="100px" prop="text">
                        <Form.input type="text" className={ cssStyle.input } value={ this.state.form.text } name='text' onChange={ this._setFormData } />
                    </Form.item>
                    <Form.item label="password：" labelWidth="100px" prop="password">
                        <Form.input type="password" className={ cssStyle.input } value={ this.state.form.password } name='password' onChange={ this._setFormData } />
                    </Form.item>
                    <Form.item label="radio：" labelWidth="100px" prop="radio">
                        <Form.radioGroup value={ this.state.form.radio } name='radio' onChange={ this.setFormData('radio') } invalid>
                            <Form.radio label="radio 1" value="1" disabled />
                            <Form.radio label="radio 2" value="2" />
                            <Form.radio label="radio 3" value="3" />
                        </Form.radioGroup>
                    </Form.item>
                    <Form.item label="textarea：" labelWidth="100px" prop="textarea">
                        <Form.input type="textarea" className={ cssStyle.input } value={ this.state.form.textarea } name='textarea' onChange={ this._setFormData } placeholder="..." />
                    </Form.item>
                    <Form.item label="checkbox：" labelWidth="100px" prop="checkbox">
                        <Form.checkboxGroup value={ this.state.form.checkbox } name='checkbox' onChange={ this._setFormData } invalid>
                            <div style={{ display: 'flex', flexDirection: 'column' }}>
                                <Form.checkbox label="checkbox 1" value="1" />
                                <Form.checkbox label="checkbox 2" value="2" disabled />
                                <Form.checkbox label="checkbox 3" value="3" />
                            </div>
                        </Form.checkboxGroup>
                    </Form.item>
                    <Form.item label="select：" labelWidth="100px" prop="select">
                        <Form.select value={ this.state.form.select } name='select' onChange={ this._setFormData } placeholder="请选择...">
                            <Form.option label="option 1" value="1" />
                            <Form.option label="option 2" value="2" />
                            <Form.option label="option 3" value="3" />
                            <Form.option label="option 4" value="4" />
                            <Form.option label="option 5" value="5" />
                            <Form.option label="option 6" value="6" />
                            <Form.option label="option 7" value="7" />
                            <Form.option label="option 8" value="8" />
                            <Form.option label="option 9" value="9" />
                            <Form.option label="option 10" value="10" />
                            <Form.option label="option 11" value="11" />
                            <Form.option label="option 12" value="12" />
                            <Form.option label="option 13" value="13" />
                            <Form.option label="option 14" value="14" />
                        </Form.select>
                    </Form.item>
                    <Form.item label="multiple：" labelWidth="100px" prop="selectMultiple">
                        <Form.select multiple value={ this.state.form.selectMultiple } name='selectMultiple' onChange={ this._setFormData } placeholder="请选择...">
                            <Form.option label="option 1" value="1" />
                            <Form.option label="option 2" value="2" />
                            <Form.option label="option 3" value="3" />
                            <Form.option label="option 4" value="4" />
                            <Form.option label="option 5" value="5" />
                            <Form.option label="option 6" value="6" />
                        </Form.select>
                    </Form.item>
                    <Form.item label="timePicker：" labelWidth="100px" prop="time">
                        <Form.timePicker value={ this.state.form.time } name='time' onChange={ this._setFormData } placeholder="请选择..." />
                    </Form.item>
                    <Form.item label="calendar：" labelWidth="100px">
                        <Form.calendar value={ this.state.form.calendar } name='calendar' onChange={ this._setFormData } placeholder="请选择..." />
                    </Form.item>
                    <Form.item label="switch：" labelWidth="100px">
                        <Form.switch value={ this.state.form.switch1 } name='switch1' activeText="开" inactiveText="关" onChange={ this._setFormData } style={{ marginRight: '20px' }} />
                    </Form.item>
                    <Form.item label="switch：" labelWidth="100px">
                        <Form.switch value={ this.state.form.switch2 } name='switch2' activeText="开" inactiveText="关" onChange={ this._setFormData } disabled />
                    </Form.item>
                    <Form.item label="upload：" labelWidth="100px">
                        <Form.upload value={ this.state.form.file } onChange={ this.getFile('file') }>
                            <Button type="primary" size="small">单点上传</Button>
                        </Form.upload>
                        <Form.upload value={ this.state.form.file } onChange={ this.getFile('file', true) }>
                            <Button type="primary" size="small">分片上传</Button>
                        </Form.upload>
                        <Form.upload value={ this.state.form.file } onChange={ this.getMultipleFile('file') } multiple={ true }>
                            <Button type="primary" size="small">单点多文件上传</Button>
                        </Form.upload>
                        <div style={{ marginTop: '8px' }}>
                            <Progress
                                percent={ this.state.percent }
                                type="line"
                                position="end"
                                strokeWidth={ 10 }
                                activeColor={
                                    [
                                        {
                                            color: '#c23a59',
                                            percent: 0
                                        },
                                        {
                                            color: '#753ac2',
                                            percent: 20
                                        },
                                        {
                                            color: '#3a70c2',
                                            percent: 40
                                        },
                                        {
                                            color: '#3ab5c2',
                                            percent: 60
                                        },
                                        {
                                            color: '#3ac270',
                                            percent: 80
                                        },
                                        {
                                            color: '#42c23a',
                                            percent: 100
                                        }
                                    ]
                                }
                                inActiveColor={ '#e5e9f2' }
                            >
                                <span>{ this.state.percent }%</span>
                            </Progress>
                        </div>
                    </Form.item>
                    {/* <Form.item label="img：" labelWidth="100px">
                        <Form.upload value={ this.state.form.img } onChange={ this.getFile('img') }>
                            <div className={ cssStyle.uploadIcon }>
                                {
                                    this.state.form.img
                                    ?
                                    <img src={ this.state.form.img } alt="img" />
                                    :
                                    <span>+</span>
                                }
                            </div>
                        </Form.upload>
                    </Form.item> */}
                    <Button type="primary" size="medium" onClick={ this.submit.bind(this) } style={{ marginLeft: '100px' }}>确定</Button>
                    <Button type="error" size="medium" onClick={ () => { this.rulesRef.current.clearValidate() } } style={{ marginLeft: '20px' }}>清除</Button>
                    <Button type="error" size="medium" onClick={ this.showPassword } style={{ marginLeft: '20px' }}>toggle</Button>
                </Form.form>
            </div>
        )
    }
}

export default FormComponent